package clientDB;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import search.SearchTuple;
import search.TagedFiles;



/**
 * this class managing the access to the client database
 * @author ran
 *
 */
public class ConnectToDataBase {

	private static ConnectToDataBase inst = new ConnectToDataBase();

	private Session session;
	/*
	 * constructor of the class
	 */
	private ConnectToDataBase() {
		SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory(); 
		session = sessionFactory.openSession();
	}
	/**
	 * 
	 * @return an instance of this class
	 */
	public static ConnectToDataBase getInst() {
		return inst;		
	}

	
	/**
	 * adding new tag algorithm to DB
	 * @param plugPath the location of the plugin
	 * @param className
	 * @param tagType
	 */
	public void addAlgo(String plugPath, String className, String tagType) {
		PlugIns plugIns = new PlugIns();
		plugIns.setClassName(className);
		plugIns.setPlugLocation(plugPath);
		plugIns.setPlugName(tagType);
		//the default is on
		plugIns.setValid(1);
		PlugInsManager pManager = new PlugInsManager(session);
		pManager.save(plugIns);
		session.flush();

	}
	/**
	 * adding file and his tags to the DB
	 * @param path file location
	 * @param labels 
	 * @param tagType the name of the tag algorithm
	 * @return
	 */
	public ArrayList<TagedFiles> addTagsToFile(String path, Set<String> labels,String tagType) {
		ArrayList<TagedFiles> tuples = new ArrayList<TagedFiles>(); 
		System.out.println("num of labels: "+ labels.size());
		String allLables[]=labels.toArray(new String[0]);
		TagedFilesManager pManager = new TagedFilesManager(session);
		System.out.println("pathBefore:"+path);
		int index=path.lastIndexOf("\\");
		System.out.println("index:"+index);
		String fileName=path.substring(index+1);
		System.out.println("fileName:"+fileName);
		String temp=path.substring(0,index);
		System.out.println("pathAfter:"+temp);
		String boxName=temp.substring(temp.lastIndexOf("\\")+1);
		System.out.println("BoxName:"+boxName);
		//delete all previous tag for this file
		Query query = session.createQuery("from TagedFiles where file_name= :fileName and box= :boxName and tag_type= :tagType" );
		query.setParameter("fileName", path);
		query.setParameter("boxName", boxName);
		query.setParameter("tagType", tagType);
		List<TagedFiles> list = query.list();
		//delete old tags
		for(TagedFiles tf : list)
			pManager.delete(tf);
		session.flush();
		//add new rows to DB with the new tags
		for(int i = 0;i<allLables.length;i++){
			TagedFiles tagedFiles=new TagedFiles();
			tagedFiles.setTag(allLables[i]);
			tagedFiles.setFileName(path);
			tagedFiles.setBoxName(boxName);
			tagedFiles.setTagType(tagType);
			pManager.save(tagedFiles);
			tuples.add(tagedFiles);

		}
		session.flush();
		return tuples;
	}
	/**
	 * change the valid bit a tag algorithm
	 * @param plugName the plug in location
	 * @param valid the new value of the valid bit
	 */
	public void changeAlgoValidBit(String plugName, int valid) {
		Query query = session.createQuery("from PlugIns where plugName= :plug_name");
		query.setParameter("plug_name", plugName);
		List<PlugIns> list = query.list();
		PlugIns plugIns=list.get(0);
		plugIns.setValid(valid);
		PlugInsManager pManager = new PlugInsManager(session);
		pManager.update(plugIns);
		session.flush();

	}
	/**
	 * search for file in DB
	 * @param tagType the name of the tagging algorithm
	 * @param tag the tag we want to find
	 * @return search result
	 */
	public ArrayList<SearchTuple> search(String tagType, String tag) {
		ArrayList<SearchTuple> ret=new ArrayList<SearchTuple>();
		Query query = session.createQuery("from TagedFiles where tag_type= :type and tag= :tag_text" );
		query.setParameter("type", tagType);
		query.setParameter("tag_text", tag);
		List<TagedFiles> list = query.list();
		//run over all tuples we got as an answer
		for(TagedFiles t : list){
			SearchTuple newFt= new SearchTuple();
			newFt.setFileName(t.getFileName());
			newFt.addTags(t.getTag());
			ret.add(newFt);
		}
		return ret;

	}
	/**
	 * search filr in DB with specific tags
	 * @param tag
	 * @return
	 */
	public ArrayList<SearchTuple> advencedSearch(ArrayList<String> tag) {
		HashMap<String,SearchTuple> mapping= new HashMap<String, SearchTuple>();
		StringBuffer qr=new StringBuffer();
		qr.append("from TagedFiles");
		String theQr=qr.toString();
		if(!tag.isEmpty()){
			qr.append(" where ");
			for(String tagInfo : tag){
				qr.append("tag= '"+tagInfo+"' or ");
			}
			theQr=qr.toString();
			theQr=theQr.substring(0, theQr.lastIndexOf("'")+1);
		}
		System.out.println("the QUARY : "+theQr);
		//run over all tags that we need to search

		Query query = session.createQuery(theQr );
		List<TagedFiles> list = query.list();
		//run over all tuples we got as an answer
		for(TagedFiles t : list){
			SearchTuple ft=mapping.get(t.getFileName());
			//new file in hash
			if(ft==null){
				SearchTuple newFt= new SearchTuple();
				newFt.setFileName(t.getFileName());
				newFt.addTags(t.getTag());
				mapping.put(t.getFileName(), newFt);
				//older file in hash
			}else{
				ft.addTags(t.getTag());
			}

		}
		ArrayList<SearchTuple> allFt = new ArrayList<SearchTuple>();
		Set<String> l = mapping.keySet();
		for(String s : l){
			allFt.add(mapping.get(s));
		}
		return allFt;

	}
	/**
	 * remove tags from file in DB
	 * @param path the file location
	 */
	public void removeTags(String path) {
		TagedFilesManager pManager = new TagedFilesManager(session);
		Query query = session.createQuery("from TagedFiles where file_name= :fileName" );
		query.setParameter("fileName", path);
		List<TagedFiles> list = query.list();
		//delete old tags
		for(TagedFiles tf : list)
			pManager.delete(tf);
		session.flush();
	}
	/**
	 * 
	 * @return all plug ins in DB
	 */
	public List<String> getPlugins() {
		System.out.println("start of AddPlugins ");
		Query query = session.createQuery("from PlugIns");
		List<PlugIns> list = query.list();
		if(list.isEmpty())
			return null;
		List<String> retList = new ArrayList<String>();
		for(PlugIns p : list){
			retList.add(p.getPlugLocation()+"\\"+p.getClassName());
		}
		System.out.println("end of AddPlugins ");
		return retList;
	}


}
